package com.sys.server.modules.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sys.server.common.constants.enums.ResultSetEnum;
import com.sys.server.common.model.R;
import com.sys.server.common.utils.MD5Util;
import com.sys.server.modules.controller.dto.UserDto;
import com.sys.server.modules.controller.vo.ImportVo;
import com.sys.server.modules.controller.vo.PageVo;
import com.sys.server.modules.controller.vo.UserInfoVo;
import com.sys.server.modules.entity.UserEntity;
import com.sys.server.modules.mapper.UserMapper;
import com.sys.server.modules.service.TokenService;
import com.sys.server.modules.service.UserService;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);

    @Resource
    private UserMapper userMapper;

    @Autowired
    private TokenService tokenService;

    @Override
    public R getUserList(Long page, Long limit) {
        IPage<UserEntity> currentPageList = new Page<>(page, limit);
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        String name = tokenService.getCurrentUser();
        wrapper.ne("uid", name);
        try {
            currentPageList = userMapper.selectPage(currentPageList, wrapper);
        } catch (Exception e) {
            LOG.error("分页查询用户列表错误");
        }
        PageVo pageVo = new PageVo();
        if (currentPageList != null) {
            pageVo.setList(currentPageList.getRecords());
            pageVo.setCurrent(page);
            pageVo.setTotal(currentPageList.getTotal());
            pageVo.setSize(limit);
            return R.ok(ResultSetEnum.SUCCESS, pageVo);
        } else {
            return R.ok(ResultSetEnum.FAIL);
        }
    }

    @Override
    public UserEntity getUserInfo(String token) {
        String uid = tokenService.getUserBytoken(token);
        UserEntity entity = userMapper.selectOne(Wrappers.<UserEntity>query().eq("uid", uid));
        if (entity != null) {
            return entity;
        } else {
            LOG.error("获取用户信息失败");
        }
        return null;
    }

    @Override
    public R addUser(UserDto userDto) {
        UserEntity user = userMapper.selectOne(Wrappers.<UserEntity>query().eq("uid", userDto.getUid()));
        if (user != null) {
            return R.ok(500, "该用户已存在");
        }
        UserEntity entity = new UserEntity();
        entity.setUid(userDto.getUid());
        entity.setName(userDto.getName());
        entity.setContact(userDto.getContact());
        entity.setDepartment(userDto.getDepartment());
        // 明文密码
        String password = userDto.getPassword();
        // 生成盐值
        String salt = MD5Util.createSalt();
        // 加密后的密码
        String passwordEncoder = MD5Util.createPwd(password, salt);
        entity.setSalt(salt);
        entity.setPwdhash(passwordEncoder);
        entity.setRole(userDto.getRole());
        try {
            int row = userMapper.insert(entity);
            if (row == 1) {
                return R.ok(ResultSetEnum.SUCCESS);
            }
        } catch (Exception e) {
            return R.ok(ResultSetEnum.FAIL);
        }
        return R.ok(ResultSetEnum.FAIL);
    }

    /**
     * 根据用户角色查询用户
     *
     * @param role
     * @return
     */
    @Override
    public R getUserListByRole(String role, Long current, Long size) {
        IPage<UserEntity> page = new Page<>(current, size);
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("role", role);
        try {
            userMapper.selectPage(page, wrapper);
        } catch (Exception e) {
            LOG.error("分页获取指定角色的用户失败");
        }
        if (page.getRecords() != null) {
            PageVo result = new PageVo();
            result.setList(page.getRecords());
            result.setCurrent(current);
            result.setSize(size);
            result.setTotal(page.getTotal());
            return R.ok(ResultSetEnum.SUCCESS, result);
        }
        return R.ok(ResultSetEnum.FAIL);
    }

    /**
     * 更新用户信息
     *
     * @param userDto
     * @return
     */
    @Override
    public R updateUserInfo(UserDto userDto) {
        String uid = userDto.getUid();
        UserEntity userEntity = userMapper.selectOne(Wrappers.<UserEntity>query().eq("uid", uid));
        UpdateWrapper<UserEntity> wrapper = new UpdateWrapper<>();
        wrapper.eq("uid", uid);
        wrapper.set("name", userDto.getName());
        wrapper.set("contact", userDto.getContact());
        wrapper.set("role", userDto.getRole());
        wrapper.set("department", userDto.getDepartment());
        try {
            int row = userMapper.update(userEntity, wrapper);
            if (row == 1) {
                return R.ok(ResultSetEnum.SUCCESS);
            } else {
                return R.ok(ResultSetEnum.FAIL);
            }
        } catch (Exception e) {
            LOG.error("更新用户信息错误");
            return R.ok(ResultSetEnum.FAIL);
        }
    }

    /**
     * 更新用户密码
     *
     * @param userDto
     * @return
     */
    @Override
    public R resetPassword(UserDto userDto) {
        // 明文密码
        String password = userDto.getPassword();
        String uid = userDto.getUid();
        UserEntity entity = userMapper.selectOne(Wrappers.<UserEntity>query().eq("uid", uid));
        String salt = entity.getSalt();
        String passwordEncoder = MD5Util.createPwd(password, salt);
        UpdateWrapper<UserEntity> wrapper = new UpdateWrapper<>();
        wrapper.eq("uid", uid);
        wrapper.set("pwdhash", passwordEncoder);
        try {
            int row = userMapper.update(entity, wrapper);
            if (row == 1) {
                return R.ok(ResultSetEnum.SUCCESS);
            } else {
                return R.ok(ResultSetEnum.FAIL);
            }
        } catch (Exception e) {
            LOG.error("重置密码错误===");
            return R.ok(ResultSetEnum.FAIL);
        }
    }

    /**
     * 批量导入用户
     *
     * @param file excel文件流
     * @return
     */
    @Override
    public R importUsers(MultipartFile file) throws IOException {
        List<HashMap<String, String>> list = new ArrayList<>();
        Long successCount = 0L;
        Long failCount = 0L;
        InputStream inputStream = file.getInputStream();
        Workbook workbook = WorkbookFactory.create(inputStream);
        // 对sheet0进行操作
        Sheet sheet = workbook.getSheetAt(0);
        // 获取总行数
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int row=1; row<rowCount; row++) {
            Row currentRow = sheet.getRow(row);

            if (isEmptyRow(currentRow)) {
                continue;
            }

            String reason = checkUserInfo(currentRow);
            if (reason != null) {
                HashMap<String, String> map = new HashMap<>();
                map.put("uid", currentRow.getCell(0).getStringCellValue());
                map.put("reason", reason);
                list.add(map);
                failCount++;
                continue;
            }

            UserEntity userEntity = new UserEntity();
            userEntity.setUid(currentRow.getCell(0).getStringCellValue());
            userEntity.setName(currentRow.getCell(1).getStringCellValue());
            String password = currentRow.getCell(2).getStringCellValue();
            String salt = MD5Util.createSalt();
            String passwordEncoder = MD5Util.createPwd(password, salt);
            userEntity.setSalt(salt);
            userEntity.setPwdhash(passwordEncoder);
            userEntity.setDepartment(currentRow.getCell(3).getStringCellValue());
            userEntity.setRole(currentRow.getCell(4).getStringCellValue());
            userEntity.setContact(currentRow.getCell(5).getStringCellValue());
            try {
                userMapper.insert(userEntity);
                successCount++;
            } catch (Exception e) {
                LOG.error("导入用户错误{}==用户信息:" + userEntity.toString() + "异常:" + e.getMessage());
                HashMap<String, String> map = new HashMap<>();
                map.put("uid", userEntity.getUid());
                map.put("reason", "导入遇到异常;");
                list.add(map);
                failCount++;
            }
        }
        ImportVo res = new ImportVo();
        res.setFailCount(failCount);
        res.setSuccessCount(successCount);
        res.setReasonList(list);
        return R.ok(ResultSetEnum.SUCCESS, res);
    }

    private boolean isEmptyRow(Row row) {
        if (row == null || row.toString().isEmpty()) {
            return true;
        } else {
            Iterator<Cell> iterator = row.iterator();
            int num = 0;
            while (iterator.hasNext()) {
                Cell cell = iterator.next();
                if (cell.getCellType() != CellType.BLANK) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 校验用户信息
     *
     * @param row 当前记录
     * @return
     */
    private String checkUserInfo(Row row) {
        StringBuffer reason = new StringBuffer();
        String uid = row.getCell(0).getStringCellValue();
        if (StringUtils.isBlank(uid)) {
            reason.append("用户名不能为空;");
        } else if (userMapper.selectOne(Wrappers.<UserEntity>query().eq("uid", uid)) != null) {
            reason.append("用户名已存在;");
        }
        String name = row.getCell(1).getStringCellValue();
        if (StringUtils.isBlank(name)) {
            reason.append("姓名不能为空;");
        }
        String password = row.getCell(2).getStringCellValue();
        if (StringUtils.isBlank(password)) {
            reason.append("密码不能为空;");
        } else if (password.length() < 6) {
            reason.append("密码不能少于6位;");
        }
        String part = row.getCell(3).getStringCellValue();
        if (StringUtils.isBlank(part)) {
            reason.append("部门不能为空;");
        }
        String role = row.getCell(4).getStringCellValue();
        if (StringUtils.isBlank(role)) {
            reason.append("角色不能为空;");
        }
        String contact = row.getCell(5).getStringCellValue();
        if (StringUtils.isBlank(contact)) {
            reason.append("联系方式不能为空;");
        }
        if (StringUtils.isNotBlank(reason.toString())) {
            return reason.toString();
        }
        return null;
    }

    /**
     * 用户信息页面返回值
     * 屏蔽密码等敏感信息
     *
     * @param userEntities
     * @return
     */
    private List<UserInfoVo> getVo(List<UserEntity> userEntities) {
        List<UserInfoVo> list = new ArrayList<>();
        for (UserEntity entity : userEntities) {
            UserInfoVo userInfoVo = new UserInfoVo();
            userInfoVo.setUid(entity.getUid());
            userInfoVo.setName(entity.getName());
            userInfoVo.setDepartment(entity.getDepartment());
            userInfoVo.setRole(entity.getRole());
            userInfoVo.setContact(entity.getContact());
            list.add(userInfoVo);
        }
        return list;
    }

}
